package scenetracer.core.shader;

import java.util.List;

import scenetracer.SceneState;
import scenetracer.SceneTracer;
import scenetracer.core.Primitive;
import scenetracer.core.Ray;
import scenetracer.core.Scene;
import scenetracer.core.Texture;
import scenetracer.core.light.Light;
import scenetracer.core.light.PointLight;
import scenetracer.image.Color;
import scenetracer.math.Point3;
import scenetracer.math.Vector3;

public abstract class Shader {
	
	protected Color dColor;
	protected Texture tex = null;
	String name;
	protected int penumbra;
	protected static final float CORRECTION = 1f;
	protected static final float FACTOR = 1f;
	
	int number;
	
	String type;
	
	public void setDColor(Color dColor) {
		this.dColor = dColor;		
	}
	
	
	public Shader(String name) {
		this.name = name;
	}
	
	public Shader(String name, int penumbra){
		this.name = name;
		this.penumbra = penumbra;
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}
	
	protected Color getPointColor(Primitive primitive, Point3 intersec) {
		if(tex == null)
			return this.dColor;
		else{
			return tex.getColorAt(primitive.getTextureCoords(intersec));
		}
	}
	
	protected Color getPenumbraColor(Color color, Vector3 normal,
			Primitive primitive, SceneState state, Scene scene, Light light, Point3 interPoint) {
		List<Vector3> dirs = light.getDirLights(state.getIntersection());
		SceneTracer trace = state.getTracer();
		float[] rands = new float[3];
		Color rayC = new Color(0,0,0);
		Color promC = new Color(Color.BLACK);
		Point3 lightRand;
		for (int i = 0; i < penumbra; i++){
			
			
			for(int j = 0; j < 3; j++)
				rands[j] = FACTOR*(2*(float)Math.random()-1);
			
			lightRand = new Point3(((PointLight)light).getLocation().x + rands[0], 
					((PointLight)light).getLocation().y + rands[1], 
					((PointLight)light).getLocation().z + rands[2]);
			
			PointLight tmpLight = new PointLight(lightRand);
		    tmpLight.setColor(light.getColor());
		    tmpLight.setPower(light.getPower());

		    Vector3 v = Point3.sub(lightRand, state.getIntersection().getIntersectionPoint(), new Vector3());
			v.normalize();
			
		    if(!trace.extraLightObs(scene, new Ray(interPoint, v), tmpLight, state.getPrimitive())){
		    	float atte = tmpLight.getAtte(interPoint);
		    	float coeff = Vector3.dot(dirs.get(0), normal);

				if( coeff > 0){
					
					Color pointColor = getPointColor(state.getPrimitive(), interPoint);
				    Color.mul((float)coeff * atte,
				    		pointColor, rayC);
				    rayC.mul(light.getColor());
				}
				
		    }
		    promC.madd(1.0f/penumbra, rayC);
		    
		}
		return promC;
	}
	
	public abstract void shade(SceneState state);	
	public abstract void setPrim(Primitive primitive);
	
}
